/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.cef.generator.coreGenerator.base.entitygen.property;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.inspur.edp.caf.generator.baseInfo.AnnotationInfo;
import com.inspur.edp.caf.generator.baseInfo.AnnotationType;
import com.inspur.edp.caf.generator.baseInfo.TypeInfo;
import com.inspur.edp.caf.generator.property.ClassPropertyGenerator;
import com.inspur.edp.caf.generator.utils.ExpressionUtils;
import com.inspur.edp.cef.designtime.api.element.GspElementObjectType;
import com.inspur.edp.cef.entity.entity.EntityDataPropertyValueUtils;
import com.inspur.edp.cef.generator.common.MediatePropertyInfo;
import com.inspur.edp.cef.generator.coreGenerator.base.entitygen.EntityGeneratorContext;
import org.eclipse.jdt.core.dom.*;

import java.util.ArrayList;

public class AssoUdtPropGenerator extends ClassPropertyGenerator {

  private final EntityGeneratorContext parentContext;
  private String belongPropName;
  private MediatePropertyInfo propertyInfo;

  public AssoUdtPropGenerator(EntityGeneratorContext parentContext,
      MediatePropertyInfo propertyInfo, String belongPropName) {
    this.parentContext = parentContext;
    this.belongPropName = belongPropName;
    this.propertyInfo = propertyInfo;
  }

  @Override
  protected boolean hasSetMethod() {
    return false;
  }

  @Override
  protected TypeInfo getPropertyType() {
    return propertyInfo.getPropertyType();
  }

  @Override
  protected String getFieldName() {
    return propertyInfo.getPropertyName();
  }

  @Override
  protected final String getPropertyName() {
    return propertyInfo.getPropertyName();
  }

  @Override
  protected ArrayList<Modifier.ModifierKeyword> getSetterAccessModifier() {
    ArrayList<Modifier.ModifierKeyword> list = new ArrayList<>();
    list.add(Modifier.ModifierKeyword.PUBLIC_KEYWORD);
    return list;
  }

  @Override
  protected ArrayList<Modifier.ModifierKeyword> getGetterAccessModifier() {
    ArrayList<Modifier.ModifierKeyword> list = new ArrayList<>();
    list.add(Modifier.ModifierKeyword.PUBLIC_KEYWORD);
    return list;
  }

  @Override
  protected Block buildGetMethodBody() {
    Block block = ast.newBlock();
    IfStatement ifStatement = getIfStatement();
    block.statements().add(ifStatement);
    ReturnStatement returnStatement = getReturnStatement();
    block.statements().add(returnStatement);

    return block;
  }

  //	@Override
//	protected BlockSyntax buildGetMethodBody()
//	{
//		java.util.ArrayList<StatementSyntax> statements = new java.util.ArrayList<StatementSyntax>();
//		IfStatementSyntax ifStatement = getIfStatement();
//		statements.add(ifStatement);
//		ReturnStatementSyntax returnStatement = getReturnStatement();
//		statements.add(returnStatement);

//		var body = SyntaxFactory.Block(statements.toArray(new StatementSyntax[]{}));
//		return body;
//	}
//
  @Override
  protected ArrayList<AnnotationInfo> getGetterAttributeList() {
    ArrayList<AnnotationInfo> list = super.getGetterAttributeList();
    if (list == null) {
      list = new ArrayList<AnnotationInfo>();
    }

    AnnotationInfo tempVar = new AnnotationInfo();
    tempVar.setAnnotationType(AnnotationType.Marker);
    tempVar.setTypeInfo(new TypeInfo(JsonIgnore.class));
    list.add(tempVar);
    return list;
  }

  //
  // if(belongProp==null){return null;}
  private IfStatement getIfStatement() {
    IfStatement statement = ast.newIfStatement();
    InfixExpression condition = ast.newInfixExpression();

    MethodInvocation invocation = ast.newMethodInvocation();
    invocation.setName(ast.newSimpleName("get" + belongPropName));
    condition.setLeftOperand(invocation);
    condition.setRightOperand(ast.newNullLiteral());
    condition.setOperator(InfixExpression.Operator.EQUALS);
    statement.setExpression(condition);
    statement.setThenStatement(getReturnDefaultStatement());

    return statement;
//		return SyntaxFactory.IfStatement(
//				SyntaxFactory.BinaryExpression(
//						SyntaxKind.EqualsExpression,
//						SyntaxFactory.IdentifierName(belongPropName),
//						SyntaxFactory.LiteralExpression(SyntaxKind.NullLiteralExpression)),
//				SyntaxFactory.Block(SyntaxFactory.<StatementSyntax>SingletonList()));
  }

  //
//	// return assoUdt.assoUdt;
  private ReturnStatement getReturnStatement() {
    String currentPropName = propertyInfo.getPropertyName();
    if (currentPropName.equals(belongPropName + "_ID")) {
      currentPropName = belongPropName;
    }
    ReturnStatement statement = ast.newReturnStatement();

//		ast.newQualifiedName(ast.newName(belongPropName),ast.newSimpleName(currentPropName))
    MethodInvocation invocation = ast.newMethodInvocation();
    invocation.setName(ast.newSimpleName("get" + belongPropName));
    statement.setExpression(
        ExpressionUtils.getMethodInvocation(ast, invocation, "get" + currentPropName));
    return statement;
//		return SyntaxFactory.ReturnStatement(
//				SyntaxFactory.MemberAccessExpression(
//						SyntaxKind.SimpleMemberAccessExpression,
//						SyntaxFactory.IdentifierName(belongPropName),
//						SyntaxFactory.IdentifierName(currentPropName)));
  }

  //
  private ReturnStatement getReturnDefaultStatement() {
    String methodName = "";
    TypeInfo propertyType = propertyInfo.getReturnType();
    ReturnStatement statement = ast.newReturnStatement();

    if (!propertyInfo.getElement().getIsUdt()
        && propertyInfo.getElement().getObjectType() == GspElementObjectType.Enum) {
      MethodInvocation invocation = ast.newMethodInvocation();
      invocation.setName(ast.newSimpleName("forValue"));
      invocation.setExpression(ast.newName(propertyType.getTypeName()));
      invocation.arguments().add(ast.newNumberLiteral("0"));
      statement.setExpression(invocation);
//			return SyntaxFactory.ReturnStatement(SyntaxFactory.DefaultExpression(TypeUtils.getTypeSyntax(propertyType)));
    }

    if (!propertyInfo.getElement().getIsUdt()
        && propertyInfo.getElement().getObjectType() == GspElementObjectType.None) {
      switch (propertyInfo.getElement().getMDataType()) {
        case String:
          methodName = "getStringPropertyDefaultValue";
          break;
        case Boolean:
          methodName = "getBoolPropertyDefaultValue";
          break;
        case Integer:
          methodName = "getIntPropertyDefaultValue";
          break;
        case Decimal:
          methodName = "getDecimalPropertyDefaultValue";
          break;
        case Date:
        case DateTime:
          methodName = "getDateTimePropertyDefaultValue";
          break;
        case Binary:
          methodName = "getBinaryPropertyDefaultValue";
          break;
        default:
          break;
      }
    }

    if (methodName == null || methodName.equals("")) {
      statement.setExpression(ast.newNullLiteral());
    } else {
      MethodInvocation invocation = ExpressionUtils
          .getMethodInvocation(ast, "EntityDataPropertyValueUtils", methodName);
      addImport(EntityDataPropertyValueUtils.class.getTypeName());
      statement.setExpression(invocation);
    }

    return statement;
  }
}
